package com.hyt.it.ogt.kq.service.bm.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hyt.check.CheckUtil;
import com.hyt.check.ruler.summary.IntRuler;
import com.hyt.check.ruler.summary.ObjRuler;
import com.hyt.common.utils.result.Result;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.FastJsonUtil;
import com.hyt.core.util.StringUtils;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.cj.model.entity.CollectImageStandard;
import com.hyt.it.ogt.cj.model.entity.CollectInfoOption;
import com.hyt.it.ogt.cj.model.entity.ProjectCollectInfoOption;
import com.hyt.it.ogt.cj.model.vo.CollResultVo;
import com.hyt.it.ogt.cj.model.vo.CollectInfoVo;
import com.hyt.it.ogt.cj.model.vo.ProjectCollectInfoVo;
import com.hyt.it.ogt.cj.service.IProjectCollectInfoService;
import com.hyt.it.ogt.kq.common.bm.enums.BmProjectNeedAuditEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmProjectNeedPayEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmProjectVerifyEnum;
import com.hyt.it.ogt.kq.common.bm.enums.CompareEnum;
import com.hyt.it.ogt.kq.common.bm.enums.CompleteStateEnum;
import com.hyt.it.ogt.kq.common.bm.enums.IsNeedAdmissionEnum;
import com.hyt.it.ogt.kq.common.bm.enums.IsRefundEnum;
import com.hyt.it.ogt.kq.common.bm.enums.NodeTypeEnum;
import com.hyt.it.ogt.kq.common.bm.enums.UpdateOrderStateEnum;
import com.hyt.it.ogt.kq.common.bm.utils.Constant;
import com.hyt.it.ogt.kq.common.bm.utils.RedisUtil;
import com.hyt.it.ogt.kq.common.config.ConfigManager;
import com.hyt.it.ogt.kq.common.config.exception.InvalidRequestException;
import com.hyt.it.ogt.kq.common.utils.KqStringUtils;
import com.hyt.it.ogt.kq.service.bm.api.model.PtBmProjectVO;
import com.hyt.it.ogt.kq.service.bm.feign.file.FileClient;
import com.hyt.it.ogt.kq.service.bm.feign.tps.TpsClient;
import com.hyt.it.ogt.kq.service.bm.mapper.NodeMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.ProjectMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.ProjectSubjectMapper;
import com.hyt.it.ogt.kq.service.bm.model.dto.ProjectNodeDTO;
import com.hyt.it.ogt.kq.service.bm.model.dto.ProjectNodeListDTO;
import com.hyt.it.ogt.kq.service.bm.model.entity.Project;
import com.hyt.it.ogt.kq.service.bm.model.entity.ProjectNode;
import com.hyt.it.ogt.kq.service.bm.model.entity.ProjectSubject;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentSubject;
import com.hyt.it.ogt.kq.service.bm.model.param.ProjectNodeBaseProjectParam;
import com.hyt.it.ogt.kq.service.bm.model.param.ProjectNodeCollectInfoParam;
import com.hyt.it.ogt.kq.service.bm.model.param.ProjectNodeParam;
import com.hyt.it.ogt.kq.service.bm.model.param.ProjectNodeSubjectParam;
import com.hyt.it.ogt.kq.service.bm.model.vo.PayStatVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.ProjectNodeAdmissionVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.ProjectNodeNoticeVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.ProjectNodePayVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.ProjectNodeVerifyVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.ProjectNodeVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.ProjectStatVo;
import com.hyt.it.ogt.kq.service.bm.service.IProject2Service;
import com.hyt.it.ogt.kq.service.bm.service.IProjectExamService;
import com.hyt.it.ogt.kq.service.bm.service.IProjectNodeService;
import com.hyt.it.ogt.kq.service.bm.service.IProjectService;
import com.hyt.it.ogt.kq.service.bm.service.IProjectSubjectService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentProjectService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentSubjectService;
import com.hyt.it.ogt.kq.service.bm.service.IUserPermissionService;
import com.hyt.loginfo.service.IBaseLoginService;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

/**
 * @Description: V2.3.12优化
 * @Author: STARF
 * @CreateDate: 2022/03/02 15:02
 **/
@RefreshScope
@Slf4j
@Service
public class Project2ServiceImpl extends BaseServiceImpl<ProjectMapper, Project> implements IProject2Service {

    @Resource
    private TpsClient tpsClient;
    @Resource
    private ConfigManager configManager;
    @Resource
    private IBaseLoginService iBaseLoginService;
    @Resource
    private IProjectNodeService iProjectNodeService;
    @Resource
    private IUserPermissionService iUserPermissionService;
    @Resource
    IProjectCollectInfoService projectCollectInfoService;
    @Resource
    private NodeMapper nodeMapper;
    @Resource
    private IProjectService iProjectService;
    @Resource
    private IStudentSubjectService iStudentSubjectService;
    @Resource
    private IStudentProjectService iStudentProjectService;
    @Resource
    private FileClient fileClient;
    @Resource
    private ProjectSubjectMapper projectSubjectMapper;
    @Resource
    private ProjectMapper projectMapper;
    @Resource
    IProjectSubjectService projectSubjectService;
    @Resource
    IProjectExamService iProjectExamService;
    @Resource
    RedisUtil redisUtil;

    @Value("${hwcloud.fileuploadpath}")
    private String bmPosterPath;


    /**
     * @Params:
     * @Description: 新增或编辑项目基本信息
     * @Author: STARF
     * @CreateDate: 2022/3/2 15:04
     **/
    @Override
    public Integer updateProjectBaseInfo(Project project) {
        Project update = this.getById(project.getId());
        if (null == update) {
            return Constant.RESPONSE_CODE_31010110;
        }

        if (StringUtils.isEmpty(update.getAddress())) {
            update.setAddress(configManager.getAddress() + "?projectId=" + project.getId() + "&officeId=" + project.getOfficeId());
        }

        if (StringUtils.isEmpty(update.getQrCodeUrl())) {
            update.setQrCodeUrl(getBmQRCodeHwCloud(project.getId(), project.getOfficeId()));
        }
        if (null == project.getIsRefund()) {
            update.setIsRefund(0);
        }

        update.setProjectName(project.getProjectName());
        update.setDescription(project.getDescription());
        update.setBeginTime(project.getBeginTime());
        update.setEndTime(project.getEndTime());
        update.setIsVerify(project.getIsVerify());
        update.setPostersUrl(project.getPostersUrl());
        if (null == update.getPayBeginTime()) {
            update.setPayBeginTime(update.getBeginTime());
        }
        if (null == update.getPayEndTime()) {
            update.setPayEndTime(update.getEndTime());
        }

        this.saveOrUpdate(update);
        return null;
    }

    /**
     * @Params: projectId 项目id
     * @Params: officeId 机构id
     * @Description: 创建项目小程序二维码
     * @Author: STARF
     * @CreateDate: 2022/3/2 15:16
     **/
    private String getBmQRCodeHwCloud(String projectId, String officeId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            String scene = "offId=";
            if (officeId.length() > 24) {
                scene = scene + officeId.substring(0, 24);
            } else {
                scene = scene + officeId;
            }
            map = (Map<String, Object>) tpsClient.getBmQRCodeHwCloud(officeId, scene, "pages/home/index", 260);
            log.info("getBmQRCodeHwCloud result :{}", JSON.toJSON(map));
        } catch (Exception e) {
            log.error("mothed: getBmQRCodeHwCloud({}, {}), msg: e={}", projectId, officeId, e);
        }
        if (null != map) {
            return String.valueOf(map.get("obj"));
        }
        return null;
    }

    /**
     * @Params:
     * @Description: 项目参数校验
     * @Author: STARF
     * @CreateDate: 2022/3/2 15:23
     **/
    @Override
    public Integer verifyProjectDate(Project project) {
        LocalDateTime now = LocalDateTime.now();
        //校验名称是否为空
        if (StringUtils.isEmpty(project.getProjectName())) {
            return Constant.RESPONSE_CODE_31010106;
        }

        //校验项目报名时间
        if (null == project.getBeginTime() || null == project.getEndTime()
                || project.getBeginTime().isBefore(now) || project.getEndTime().isBefore(now)
                || project.getBeginTime().isAfter(project.getEndTime())) {
            return Constant.RESPONSE_CODE_31010106;
        }

        //校验项目时间逻辑
        if (null != project.getRefuseTime() && (project.getRefuseTime().isBefore(project.getBeginTime()) || project.getRefuseTime().isAfter(project.getEndTime()))) {
            return Constant.RESPONSE_CODE_31010102;
        }
        if (null != project.getPayBeginTime() && (project.getPayBeginTime().isBefore(project.getBeginTime()) || project.getPayBeginTime().isAfter(project.getEndTime()))) {
            return Constant.RESPONSE_CODE_31010103;
        }
        if (null != project.getPayEndTime() && (project.getPayEndTime().isBefore(project.getBeginTime()) || project.getPayEndTime().isAfter(project.getEndTime()))) {
            return Constant.RESPONSE_CODE_31010103;
        }

        //校验同机构下面项目名称是否重复
        QueryWrapper<Project> tempwrapper = new QueryWrapper<Project>();
        tempwrapper.eq("office_id", project.getOfficeId());
        tempwrapper.eq("project_name", project.getProjectName());
        if (StringUtils.isNotEmpty(project.getId())) {
            tempwrapper.ne("id", project.getId());
        }
        List<Project> projectList = this.list(tempwrapper);
        if (CollectionUtils.isNotEmpty(projectList)) {
            return Constant.RESPONSE_CODE_31010106;
        }
        return null;
    }

    /**
     * @Params:
     * @Description: 项目流程
     * @Author: STARF
     * @CreateDate: 2022/3/2 16:39
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer setProjectNode(ProjectNodeListDTO listDTO) {
        List<ProjectNodeDTO> projectNodeDTOList = listDTO.getProjectNodeDTOList();
        String projectId = listDTO.getProjectId();
        Project project = this.getById(projectId);
        if (null == project) {
            return Constant.RESPONSE_CODE_31010110;
        }

        List<ProjectNode> list = new ArrayList<>();
        projectNodeDTOList.forEach(dto -> {
            ProjectNode node = ProjectNode.builder().build();
            BeanUtils.copyProperties(dto, node);
            if (StringUtils.isEmpty(node.getId())) {
                node.setId(UUIDUtils.newSortUUID());
            }

            if (node.getNodeType().equals(NodeTypeEnum.NOTICE.getCode()) && StringUtils.isEmpty(node.getNodeOrder())) {
                node.setNodeOrder("1");
            }
            node.setNodeName(NodeTypeEnum.getTypeMsg(node.getNodeType()));
            list.add(node);

            //设置项目退费
            if (node.getNodeType().equals(NodeTypeEnum.PAY.getCode())) {
                project.setIsRefund(node.getDelFlag() ? 1 : 0);
                this.saveOrUpdate(project);
            }
        });

        iProjectNodeService.saveOrUpdateBatch(list);
        return null;
    }

    /**
     * @Params: projectId   项目id
     * @Description: 获取报名流程列表
     * @Author: STARF
     * @CreateDate: 2022/3/3 9:48
     **/
    @Override
    public List<ProjectNodeVo> queryProjectNode(String projectId) {
        Project project = this.getById(projectId);
        if (null == project) {
            return null;
        }
        List<ProjectNodeVo> list = iProjectNodeService.queryNodeList(projectId);
        List<ProjectNodeVo> voList = new ArrayList<>();
        list.forEach(p -> {
            ProjectNodeVo vo = new ProjectNodeVo();
            BeanUtils.copyProperties(p, vo);
            if (vo.getNodeType().equals(NodeTypeEnum.PAY.getCode())) {
                vo.setBeginTime(project.getPayBeginTime());
                vo.setEndTime(project.getPayEndTime());
            }
            if (vo.getNodeType().equals(NodeTypeEnum.ADMISSION.getCode())) {
                vo.setBeginTime(project.getAdmissionBeginTime());
                vo.setEndTime(project.getAdmissionEndTime());
            }
            if (vo.getNodeType().equals(NodeTypeEnum.VERIFY.getCode())) {
                vo.setEndTime(project.getAuditEndTime());
            }
            voList.add(vo);
        });
        return voList;
    }

    /**
     * @Params:
     * @Description: 启用/禁用流程
     * @Author: STARF
     * @CreateDate: 2022/3/3 10:04
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer activeNode(ProjectNodeDTO dto) {
        Project project = this.getById(dto.getProjectId());
        if (null == project) {
            return Constant.RESPONSE_CODE_31010110;
        }
        ProjectNode projectNode = iProjectNodeService.getById(dto.getId());
        if (null == projectNode) {
            return Constant.RESPONSE_CODE_31241402;
        }

        //报名须知
        if (dto.getNodeType().equals(NodeTypeEnum.NOTICE.getCode())) {
            //处理老数据
            List<ProjectNodeVo> nodeVoList = nodeMapper.queryNodeList(dto.getProjectId());
            nodeVoList.forEach(node -> {
                node.setUpdateBy(iBaseLoginService.getUserId());
                node.setDelFlag(dto.getDelFlag());
                nodeMapper.updateNodeList(node);
            });
        }

        //资格审核
        if (dto.getNodeType().equals(NodeTypeEnum.VERIFY.getCode())) {
            if (project.getStatus() == 1) {
                return Constant.RESPONSE_CODE_31241401;
            }
            project.setIsVerify(dto.getDelFlag() ? 1 : 0);
        }

        //缴费
        if (dto.getNodeType().equals(NodeTypeEnum.PAY.getCode())) {
            //已发布的报名不能修改缴费状态
            if (project.getStatus() == 1) {
                return Constant.RESPONSE_CODE_31051102;
            }
            //若已有报名，则不能修改项目是否需要缴费
            String deptId = "";
            if (0 == project.getIsOpen()) {
                deptId = iBaseLoginService.getDeptId();
            }
            List<String> permissionList = new ArrayList<String>();
            boolean flag = iUserPermissionService.needCheckAreaPermission(project.getId());
            if (flag) {
                permissionList = iUserPermissionService.queryPermissionByUserId(project.getId(), iBaseLoginService.getUserId());
                if (permissionList != null && permissionList.size() == 0) {
                    permissionList = new ArrayList<String>();
                    permissionList.add("NoPermission");//如果是无权限，设置一个不存在的权限
                }
            }
            ProjectStatVo vo = iProjectService.statProjectStudent(project.getId(), permissionList, deptId);
            if (null != vo && vo.getApplyNum() > 0) {
                return Constant.RESPONSE_CODE_31051103;
            }
            project.setIsPay(dto.getDelFlag() ? 1 : 0);

            //将项目下所有的需缴费的科目改为免费
            if (!projectNode.getDelFlag() && dto.getDelFlag()) {
                List<ProjectSubject> projectSubjectList = projectSubjectMapper.getSubjectList(project.getId(), null, null);
                for (ProjectSubject projectSubject : projectSubjectList) {
                    if (projectSubject.getIsPay() == 1) {
                        ProjectSubject subject = new ProjectSubject();
                        subject.setIsPay(0);
                        subject.setPrice(BigDecimal.ZERO);
                        subject.setSubjectId(projectSubject.getSubjectId());
                        subject.setProjectId(projectSubject.getProjectId());
                        subject.setSubjectName(projectSubject.getSubjectName());
                        subject.setDescription(projectSubject.getDescription());
                        subject.setId(projectSubject.getId());
                        projectSubjectMapper.updateById(subject);
                    }
                }
            }
        }

        //打印准考证
        if (dto.getNodeType().equals(NodeTypeEnum.ADMISSION.getCode())) {
            project.setIsNeedAdmission(dto.getDelFlag() ? 1 : 0);
        }

        this.saveOrUpdate(project);

        projectNode.setDelFlag(dto.getDelFlag());
        iProjectNodeService.saveOrUpdate(projectNode);

        return null;
    }

    /**
     * @Params:
     * @Description: 流程缴费设置
     * @Author: STARF
     * @CreateDate: 2022/3/3 10:59
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer setProjectPay(Project project) {
        Project project2 = iProjectService.getById(project.getId());
        if (null == project2) {
            return Constant.RESPONSE_CODE_31010110;
        }

        //时间校验
        if (null != project.getRefuseTime() && (project.getRefuseTime().isBefore(project.getBeginTime()) || project.getRefuseTime().isAfter(project.getEndTime()))) {
            return Constant.RESPONSE_CODE_31051105;
        }
        if (null != project.getPayBeginTime() && (project.getPayBeginTime().isBefore(project.getBeginTime()) || project.getPayBeginTime().isAfter(project.getEndTime()))) {
            return Constant.RESPONSE_CODE_31051106;
        }
        if (null != project.getPayEndTime() && (project.getPayEndTime().isBefore(project.getBeginTime()) || project.getPayEndTime().isAfter(project.getEndTime()))) {
            return Constant.RESPONSE_CODE_31051106;
        }

        project2.setPayEndTime(project.getPayEndTime());
        project2.setPayBeginTime(project.getPayBeginTime());
        project2.setRefuseTime(project.getRefuseTime());
        project2.setIsRefund(project.getIsRefund());
        this.saveOrUpdate(project2);

        return null;
    }

    /**
     * @Params:
     * @Description: 流程打印准考证设置
     * @Author: STARF
     * @CreateDate: 2022/3/3 11:15
     **/
    @Override
    public Integer setProjectAdmissionTime(Project project) {
        Project project2 = iProjectService.getById(project.getId());
        if (null == project2) {
            return Constant.RESPONSE_CODE_31010110;
        }

        project2.setAdmissionBeginTime(project.getAdmissionBeginTime());
        project2.setAdmissionEndTime(project.getAdmissionEndTime());
        this.saveOrUpdate(project2);

        return null;
    }

    /**
     * @Params:
     * @Description: 报名须知设置
     * @Author: STARF
     * @CreateDate: 2022/3/3 16:52
     **/
    @Override
    public Integer setNotice(ProjectNodeDTO dto) {
        ProjectNode node = iProjectNodeService.getById(dto.getId());
        if (null == node) {
            return Constant.RESPONSE_CODE_31241402;
        }
        node.setDelFlag(dto.getDelFlag());
        node.setNodeTitle(dto.getNodeTitle());
        node.setNodeContent(dto.getNodeContent());
        node.setButtonIsTime(dto.getButtonIsTime());
        node.setButtonTime(dto.getButtonTime());
        node.setButtonName(dto.getButtonName());
        node.setNodeName(NodeTypeEnum.NOTICE.name());
        iProjectNodeService.updateById(node);
        return null;
    }


    /**
     * @Params:
     * @Description: 报名海报上传华为云
     * @Author: STARF
     * @CreateDate: 2022/3/7 16:17
     **/
    @Override
    public void updatePosterUrl() {
        QueryWrapper<Project> wrapper = new QueryWrapper<>();
        wrapper.lambda().isNotNull(Project::getPostersUrl).ne(Project::getPostersUrl, "");
        List<Project> list = iProjectService.list(wrapper);
        for (Project project : list) {
            String postersUrl = project.getPostersUrl();
            try {
                if (postersUrl.contains(Constant.HTTP) || !postersUrl.contains(".") || KqStringUtils.checkStringContainChinese(postersUrl)) {
                    continue;
                }
                String path = bmPosterPath + "poster/" + project.getId() + postersUrl.substring(postersUrl.indexOf("."));
                log.info(path);
                byte[] bytes = fileClient.downFile(postersUrl);
                if (ArrayUtil.isEmpty(bytes)) {
                    log.error("projectId={}, postersUrl={}, 海报图片不存在", project.getId(), project.getPostersUrl());
                    continue;
                }
                Result result = tpsClient.uploadFileToHuawei(project.getOfficeId(), path, bytes);
                if (result.getSuccess()) {
                    result.setObj(result.getObj().toString().replace("%2F", "/"));
                    project.setPostersUrl(result.getObj().toString());
                    this.saveOrUpdate(project);
                }
            } catch (Exception e) {
                log.error("projectId={}, postersUrl={}", project.getId(), project.getPostersUrl());
                log.error(e.getMessage());
                return;
            }

        }
    }


    /**
     * @Params:
     * @Description: 查询考生须知
     * @Author: STARF
     * @CreateDate: 2022/3/28 9:44
     **/
    @Override
    public ProjectNode getProjectNotice(String projectId) throws InvalidRequestException {
        Project project = iProjectService.getById(projectId);
        if (null == project) {
            throw new InvalidRequestException(Constant.RESPONSE_CODE_31010110);
        }

        if (null == project.getIsNotice() || 0 == project.getIsNotice()) {
            throw new InvalidRequestException(Constant.RESPONSE_CODE_31241801);
        }

        QueryWrapper<ProjectNode> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(ProjectNode::getProjectId, projectId)
                .isNotNull(ProjectNode::getNodeContent)
                .ne(ProjectNode::getNodeContent, "")
                .orderByAsc(ProjectNode::getNodeNumber);
        wrapper.and((wra) -> {
            wra.lambda().eq(ProjectNode::getDelFlag, false).or().isNull(ProjectNode::getDelFlag);
        });
        List<ProjectNode> list = iProjectNodeService.list(wrapper);
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }


    /**
     * @Params:
     * @Description: 平台获取报名基本信息列表(限制50条任务)
     * @Author: STARF
     * @CreateDate: 2022/5/30 9:55
     **/
    @Override
    public List<PtBmProjectVO> ptQueryProjectNameList(String officeId, String projectName) {
        QueryWrapper<Project> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(projectName)) {
            wrapper.lambda().like(Project::getProjectName, "%" + projectName + "%");
        }
        wrapper.lambda().eq(Project::getOfficeId, officeId).eq(Project::getDelFlag, false).last("limit 50").orderByDesc(Project::getCreateDate);
        List<Project> list = iProjectService.list(wrapper);
        return list.stream().map(p -> {
            PtBmProjectVO vo = new PtBmProjectVO();
            BeanUtils.copyProperties(p, vo);
            vo.setProjectId(p.getId());
            vo.setBeginTime(p.getBeginTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            vo.setEndTime(p.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            vo.setTimeStatus(this.projectTimeStatus(p));
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * @Params:
     * @Description: 平台获取报名任务报考数据
     * @Author: STARF
     * @CreateDate: 2022/5/30 9:55
     **/
    @Override
    public List<PtBmProjectVO> ptQueryProjectInfo(String projectId) {
        List<String> idList = Arrays.asList(projectId.split(","));
        List<Project> list = iProjectService.listByIds(idList);

        return this.projectsInfo(list);
    }

    /**
     * @Params:
     * @Description: 平台获取报名任务报考信息列表(限制50条任务)
     * @Author: STARF
     * @CreateDate: 2022/5/30 9:55
     **/
    @Override
    public List<PtBmProjectVO> ptQueryProjectList(String officeId, String projectName) {
        QueryWrapper<Project> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(projectName)) {
            wrapper.lambda().like(Project::getProjectName, "%" + projectName + "%");
        }
        wrapper.lambda().eq(Project::getOfficeId, officeId).eq(Project::getDelFlag, false).last("limit 50").orderByDesc(Project::getCreateDate);
        List<Project> list = iProjectService.list(wrapper);

        return this.projectsInfo(list);
    }

    /**
     * @Params:
     * @Description:
     * @Author: STARF
     * @CreateDate: 2022/6/1 11:33
     **/
    public List<PtBmProjectVO> projectsInfo(List<Project> list) {
        return list.stream().map(p -> {
            PtBmProjectVO vo = new PtBmProjectVO();
            BeanUtils.copyProperties(p, vo);
            vo.setProjectId(p.getId());
            vo.setBeginTime(p.getBeginTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            vo.setEndTime(p.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

            List<String> permissionList = new ArrayList<String>();
            ProjectStatVo statVo = iProjectService.statProjectStudent(p.getId(), permissionList, "");
            ProjectStatVo subjectVo = iProjectService.statProjectSubject(p.getId(), permissionList, "");
            int payManTime = 0;
            List<PayStatVo> payStatVoList = iStudentSubjectService.statPayByProjectId(p.getId(), permissionList, "");
            if (payStatVoList != null && payStatVoList.size() > 0) {
                for (PayStatVo payStatVo : payStatVoList) {
                    if (payStatVo.getPayNum() > 0) {
                        payManTime++;
                    }
                }
            }

            if (null != statVo) {
                vo.setApplyNum(statVo.getApplyNum());
                vo.setUnAuditNum(statVo.getAuditNum());
            }
            if (subjectVo != null) {
                vo.setPayManNum(subjectVo.getPayManTime());
//                vo.setUnAuditNum(subjectVo.getAuditNum());
            }
            if (payStatVoList != null && payStatVoList.size() > 0) {
                vo.setPayManNum(payManTime);
            }
            if (p.getIsVerify() == 0) {
                vo.setUnAuditNum(0);
            }
            vo.setTimeStatus(this.projectTimeStatus(p));
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * @Params:
     * @Description: 获取报名状态
     * @Author: STARF
     * @CreateDate: 2022/5/30 11:24
     **/
    private Integer projectTimeStatus(Project project) {
        Integer timeStatus;
        if (project.getBeginTime().isAfter(LocalDateTime.now())) {
            //未开始
            timeStatus = 0;
        } else if (project.getBeginTime().isBefore(LocalDateTime.now()) && project.getEndTime().isAfter(LocalDateTime.now())) {
            timeStatus = 1;
        } else {
            timeStatus = 2;
        }
        return timeStatus;
    }

    /**
     * @Params:
     * @Description: 平台分页获取报名项目数据
     * @Author: STARF
     * @CreateDate: 2022/6/8 8:37
     **/
    @Override
    public Page<PtBmProjectVO> ptGetProjectPage(PtBmProjectVO vo) {
        List<Project> list = projectMapper.ptQueryProject(vo, LocalDateTime.now());
        Page<PtBmProjectVO> page = new Page<>();
        List<PtBmProjectVO> voList = this.projectsInfo(list);
        page.setCurrent(vo.getCurrent());
        page.setRecords(voList);
        page.setSize(vo.getSize());
        page.setTotal(projectMapper.ptcountProject(vo, LocalDateTime.now()));
        return page;
    }

    /**
     * @Params:
     * @Description: 平台绑定操作
     * @Author: STARF
     * @CreateDate: 2022/6/8 9:17
     **/
    @Override
    public Boolean ptBangProject(String projectId, Integer bangFlag) {
        List<String> ids = Arrays.asList(projectId.split(","));
        if (1 == bangFlag || 0 == bangFlag) {
            projectMapper.ptBangProject(ids, bangFlag);
            return true;
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String saveBaseProject(ProjectNodeBaseProjectParam param) {
        // 校验报名项目基础数据有效性
        verifyProjectBaseData(param);
        Project project = BeanUtil.toBean(param, Project.class);
        String projectId = UUIDUtils.newSortUUID();
        project.setCompleteState(CompleteStateEnum.CREATE.getCode())
                .setUpdateOrderState(UpdateOrderStateEnum.NO.getCode())
                .setIsCompare(CompareEnum.NO.getCode())
                .setIsNeedAdmission(IsNeedAdmissionEnum.NO.getCode())
                .setCreateBy(iBaseLoginService.getUserId())
                .setCreateDate(LocalDateTime.now())
                .setUpdateBy(iBaseLoginService.getUserId())
                .setUpdateDate(LocalDateTime.now())
                .setDelFlag(Boolean.TRUE)
                .setId(projectId);
        String bmAddress = configManager.getAddress() + "?projectId=" + projectId + "&officeId=" + project.getOfficeId();
        project.setAddress(bmAddress);
        String qrCodeUr = createBmQrCode(project.getOfficeId());
        project.setQrCodeUrl(qrCodeUr);
        projectMapper.insert(project);
        return project.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String editBaseProject(ProjectNodeBaseProjectParam param) {
        Project oldProject = iProjectService.getProjectById(param.getId());
        param.setOfficeId(oldProject.getOfficeId());

        // 校验报名项目基础数据有效性
        verifyProjectBaseData(param);
        Project project = BeanUtil.toBean(param, Project.class);
        project.setUpdateBy(iBaseLoginService.getUserId())
                .setUpdateDate(LocalDateTime.now())
                .setDelFlag(null);
        this.updateById(project);
        return project.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String saveProjectNode(ProjectNodeParam param) {
        // 检查报名下是否有考生报名
        //iStudentProjectService.checkHasStudent(param.getProjectId());
        // 检查是否绑定考务
        //iProjectExamService.checkHasBindKwGov(param.getProjectId());
        // 校验报名节点数据
        String projectId = param.getProjectId();
        checkProjectNodeData(projectId, param.getNodeList());
        List<ProjectNodeVo> nodeList = param.getNodeList();
        // 获取报名数据
        Project project = assembleProjectBaseInfo(param);
        // 将报名节点数据保存
        List<ProjectNode> projectNodes = nodeList.stream()
                .map(data -> {
                    ProjectNode projectNode = BeanUtil.toBean(data, ProjectNode.class);
                    if (ObjectUtil.isEmpty(projectNode.getId())) {
                        projectNode.setProjectId(param.getProjectId());
                        projectNode.setCreateBy(iBaseLoginService.getUserId()).setCreateDate(LocalDateTime.now());
                    }
                    projectNode.setUpdateBy(iBaseLoginService.getUserId()).setUpdateDate(LocalDateTime.now());
                    return projectNode;
                }).collect(Collectors.toList());

        iProjectNodeService.saveOrUpdateBatch(projectNodes);

        // 如果项目不需要缴费，清空科目的缴费标识和金额
        Integer isPay = project.getIsPay();
        if (null != isPay && BmProjectNeedPayEnum.UNPAY.getPayStatus().equals(isPay)) {
            // 查询是否有科目信息
            List<ProjectSubject> projectSubjects = projectSubjectService.getProjectSubjectsByProjectId(projectId);
            int payStauts = 0;
            if (CollUtil.isNotEmpty(projectSubjects)) {
                for (ProjectSubject projectSubject : projectSubjects) {
                    payStauts += projectSubject.getIsPay();
                }
            }
            if (payStauts > 0) {
                throw new InvalidRequestException(31242319, "存在缴费的科目设置，不允许修改缴费状态为不需要缴费！");
            }
        }
        projectMapper.updateById(project);
        return param.getProjectId();
    }

    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    @Override
    public String saveProjectCollect(ProjectNodeCollectInfoParam param) {
        // 检查报名下是否有考生报名
        iStudentProjectService.checkHasStudent(param.getProjectId());
        // 检查是否绑定考务
        iProjectExamService.checkHasBindKwGov(param.getProjectId());
        // 首先给所有的采集信息字段排序
        int orderNum = 1;
        for (ProjectCollectInfoVo projectCollectInfoVo : param.getCollectInfoList()) {
            projectCollectInfoVo.setOrderNum(orderNum);
            orderNum++;
            int optionOrderNum = 1;
            if (CollUtil.isNotEmpty(projectCollectInfoVo.getOptionList())) {
                for (ProjectCollectInfoOption projectCollectInfoOption : projectCollectInfoVo.getOptionList()) {
                    projectCollectInfoOption.setOrderNum(optionOrderNum);
                    optionOrderNum++;
                }
            }
        }
        // 判断是新增还是修改采集信息
        if (CollUtil.isNotEmpty(param.getCollectInfoList())) {
            // 查询是否存在采集信息实例化
            List<ProjectCollectInfoVo> projectCollectInfoVos = projectCollectInfoService.queryByProjectId(param.getProjectId());
            // 如果已经存在，说明已经有采集信息落库并做二次修改
            if (CollUtil.isNotEmpty(projectCollectInfoVos)) {
                param.getCollectInfoList().forEach(projectCollectInfoVo -> projectCollectInfoVo.setProjectId(param.getProjectId()));
                CollResultVo collResultVo = projectCollectInfoService.updateProjectCollectInfoV2(param.getCollectInfoList(), param.getProjectId());
                if (!CollResultVo.isSuccess(collResultVo.getCode())) {
                    throw new InvalidRequestException(collResultVo.getCode(), collResultVo.getMsg());
                }
            } else {
                List<CollectInfoVo> list = new ArrayList<>();
                param.getCollectInfoList().forEach(p -> {
                    CollectInfoVo vo = new CollectInfoVo();
                    BeanUtils.copyProperties(p, vo);
                    if (null != p.getCollectImageStandard()) {
                        CollectImageStandard standard = new CollectImageStandard();
                        BeanUtils.copyProperties(p.getCollectImageStandard(), standard);
                        vo.setCollectImageStandard(standard);
                    }
                    if (CollectionUtils.isNotEmpty(p.getOptionList())) {
                        List<CollectInfoOption> optionList = new ArrayList<>();
                        p.getOptionList().forEach(o -> {
                            CollectInfoOption option = new CollectInfoOption();
                            BeanUtils.copyProperties(o, option);
                            optionList.add(option);
                        });
                        vo.setOptionList(optionList);
                    }
                    list.add(vo);
                });
                CollResultVo collResultVo = projectCollectInfoService.saveProjectCollectInfoBatchV2(list, param.getProjectId());
                if (!CollResultVo.isSuccess(collResultVo.getCode())) {
                    throw new InvalidRequestException(collResultVo.getCode(), collResultVo.getMsg());
                }
            }
        }
        return param.getProjectId();
    }

    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    @Override
    public String saveProjectSubject(ProjectNodeSubjectParam param) {
        // 检查报名下是否有考生报名
        iStudentProjectService.checkHasStudent(param.getProjectId());
        log.info("# saveProjectSubject :{}", FastJsonUtil.getBeanToJson(param));
        // 检查是否绑定考务
        iProjectExamService.checkHasBindKwGov(param.getProjectId());
        Project project = iProjectService.getProjectById(param.getProjectId());

        if (param.getMaxSubject() > param.getSubjectList().size()) {
            throw new InvalidRequestException(Constant.RESPONSE_CODE_31051110, "报名科目数与实际科目数不匹配");
        }
        if (param.getMaxSubject() <= 0) {
            throw new InvalidRequestException(Constant.RESPONSE_CODE_31051110, "报名科目数与实际科目数不匹配");
        }
        if (param.getMinSubject() > param.getSubjectList().size()) {
            throw new InvalidRequestException(Constant.RESPONSE_CODE_31051110, "报名科目数与实际科目数不匹配");
        }
        if (param.getMinSubject() <= 0) {
            throw new InvalidRequestException(Constant.RESPONSE_CODE_31051110, "报名科目数与实际科目数不匹配");
        }

        List<ProjectSubject> list = projectSubjectService.querySubjectList(param.getProjectId(), null);
        List<ProjectSubject> voList = param.getSubjectList();

        if (CollUtil.isNotEmpty(voList)) {
            HashMap<String, Integer> map = new HashMap<>();
            //list - projectVo.getSubjectList()取交集，交集删除
            if (CollUtil.isNotEmpty(list)) {
                list.stream()
                        .filter(item ->
                                !voList.stream()
                                        .map(ProjectSubject::getSubjectId)
                                        .collect(Collectors.toList())
                                        .contains(item.getSubjectId()))
                        .forEach(e -> {
                            try {
                                List<StudentSubject> ssList = iStudentSubjectService.queryStudentSubject(null, null, e.getSubjectId(), null, new ArrayList<String>(), param.getProjectId());
                                if (CollUtil.isNotEmpty(ssList)) {
                                    throw new InvalidRequestException(Constant.RESPONSE_CODE_31061501, "当前科目已有学生报名，不能删除");
                                }
                                projectSubjectService.deleteSubject(e.getId(), e.getProjectId(), e.getSubjectId());
                            } catch (InvalidRequestException invalidRequestException) {
                                throw invalidRequestException;
                            } catch (Exception exc) {
                                throw new InvalidRequestException(Constant.RESPONSE_CODE_31061502, "科目删除异常");
                            }
                        });
            }

            //科目名称判重
            voList.forEach(s -> map.merge(s.getSubjectName(), 1, Integer::sum));
            for (Map.Entry<String, Integer> me : map.entrySet()) {
                if (me.getValue() > 1) {
                    throw new InvalidRequestException(Constant.RESPONSE_CODE_31010144, "科目已存在");
                }
            }

            for (ProjectSubject subject : voList) {
                // 如果科目ID不存在，则给一个新的ID
                if (StrUtil.isBlank(subject.getId())) {
                    subject.setId(UUIDUtils.newSortUUID());
                }
                if (StrUtil.isEmpty(subject.getProjectId())) {
                    subject.setProjectId(param.getProjectId());
                }
                if (null == subject.getDelFlag()) {
                    subject.setDelFlag(false);
                }
                if (subject.getPrice() != null && subject.getPrice().doubleValue() > ConfigManager.MAXPRICE) {
                    throw new InvalidRequestException(Constant.RESPONSE_CODE_31010145, "科目价格超过最大值");
                }
                if (0 == project.getIsPay() && null != subject.getIsPay() && 1 == subject.getIsPay()) {
                    throw new InvalidRequestException(Constant.RESPONSE_CODE_31010108, "科目缴费状态须在报名项目规定范围内");
                }
                if (null != subject.getIsPay() && 1 == subject.getIsPay() && (null == subject.getPrice() || BigDecimal.ZERO.equals(subject.getPrice()))) {
                    throw new InvalidRequestException(Constant.RESPONSE_CODE_31051109, "科目信息不完整");
                }
                if (StrUtil.isEmpty(subject.getSubjectName())) {
                    throw new InvalidRequestException(Constant.RESPONSE_CODE_31051109, "科目信息不完整");
                }
                if (StrUtil.isEmpty(subject.getSubjectId())) {
                    subject.setSubjectId(UUIDUtils.newSortUUID());
                } else {
                    //已有考生的报名的科目，不能更新编辑
                    list.forEach(sub -> {
                        if (subject.getSubjectId().equals(sub.getSubjectId())) {
                            List<StudentSubject> studentSubjectList = iStudentSubjectService.queryStudentSubject(null, null, sub.getSubjectId(), null, new ArrayList<String>(), param.getProjectId());
                            if (CollUtil.isNotEmpty(studentSubjectList) && iProjectService.hasChangeSubject(subject, sub)) {
                                throw new InvalidRequestException(Constant.RESPONSE_CODE_31061503, "已有学生报名，原有科目不能编辑");
                            }
                            // 判断修改的科目信息和实际的报考信息是否一致
                            // 获取当前科目的报名人数
                            Integer regestSubjectCount = projectSubjectService.getCurrentRegSubjectCount(param.getProjectId(), sub.getSubjectId());
                            Integer maxNumberofRegister = subject.getMaxNumberofRegister();
                            if (subject.getLimitSubjectRegister() == 1 && regestSubjectCount.compareTo(maxNumberofRegister) > 0) {
                                throw new InvalidRequestException(Constant.RESPONSE_CODE_31061504, "科目设置的最大报名数，超过已经报名人数，请修改后重新设置！");
                            }
                        }
                    });
                }
                if (StrUtil.isEmpty(subject.getId())) {
                    subject.setId(UUIDUtils.newSortUUID());
                }
            }
            log.info("# saveProjectSubject voList:{}", FastJsonUtil.getBeanToJson(voList));
            for (ProjectSubject projectSubject : voList) {
                // 如果部门ID为空，则用当前登录人的部门ID
                if (StrUtil.isBlank(projectSubject.getDeptId())) {
                    projectSubject.setDeptId(project.getDeptId());
                }
                projectSubject.setOfficeId(project.getOfficeId())
                        .setUpdateBy(iBaseLoginService.getUserId())
                        .setUpdateDate(LocalDateTime.now());
            }
            projectSubjectService.saveOrUpdateBatch(voList);
        } else {
            projectSubjectService.deleteSubjectByProjectId(param.getProjectId());
        }

        Project updateProject = new Project();
        updateProject.setMaxSubject(param.getMaxSubject())
                .setMinSubject(param.getMinSubject())
                .setId(project.getId())
                .setUpdateBy(iBaseLoginService.getUserId())
                .setUpdateDate(LocalDateTime.now());
        iProjectService.updateById(updateProject);

        return param.getProjectId();
    }

    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    @Override
    public String projectTempToMain(String projectId) {
        Project project = iProjectService.getProjectById(projectId);

        // 获取报名流程节点
        List<ProjectNodeVo> projectNodeVos = iProjectService.queryNodeList(projectId);
        if (CollUtil.isEmpty(projectNodeVos)) {
            InvalidRequestException.throwException(31242802, "报名流程节点数据缺失");
        }

        // 获取报名采集项
        List<ProjectCollectInfoVo> projectCollectInfoVos = projectCollectInfoService.queryByProjectId(projectId);
        if (CollUtil.isEmpty(projectCollectInfoVos)) {
            InvalidRequestException.throwException(31242803, "报名采集信息数据缺失");
        }

        // 获取报考科目
        List<ProjectSubject> projectSubjects = projectSubjectService.querySubjectList(projectId, null);
        if (CollUtil.isEmpty(projectSubjects)) {
            InvalidRequestException.throwException(31242804, "报考科目数据缺失");
        }

        //校验项目时间逻辑
        if (null != project.getRefuseTime() && (project.getRefuseTime().isBefore(project.getBeginTime()) || project.getRefuseTime().isBefore(project.getPayEndTime()))) {
            InvalidRequestException.throwException(31051001, "请将退费截止时间设置在报名缴费截止时间之后");
        }
        // 如果项目需要审核，且审核时间不为空
        if (BmProjectNeedAuditEnum.NEEDAUDIT.getAuditStatus().equals(project.getIsVerify()) && null != project.getAuditEndTime()) {
            // 如果需要缴费, 缴费的开始时间应该在报名时间之后，以及审核结束时间之后
            if (BmProjectNeedPayEnum.PAY.getPayStatus().equals(project.getIsPay()) && null != project.getPayBeginTime() && project.getPayBeginTime().isBefore(project.getBeginTime())) {
                InvalidRequestException.throwException(31051010, "请将缴费开始时间设置在报名开始时间之后");
            }
            // 如果需要缴费, 缴费的结束时间应该在报名时间之后，以及审核结束时间之后
            if (BmProjectNeedPayEnum.PAY.getPayStatus().equals(project.getIsPay()) && null != project.getPayEndTime() && (project.getPayEndTime().isBefore(project.getBeginTime()) || project.getPayEndTime().isBefore(project.getAuditEndTime()))) {
                InvalidRequestException.throwException(31051009, "请将缴费结束时间设置在报名审核截止时间之后");
            }
        } else {
            // 如果不需要审核 需要缴费, 缴费的开始时间应该在报名时间之后，以及审核结束时间之后
            if (BmProjectNeedPayEnum.PAY.getPayStatus().equals(project.getIsPay()) && null != project.getPayBeginTime() && project.getPayBeginTime().isBefore(project.getBeginTime())) {
                InvalidRequestException.throwException(31051010, "请将缴费开始时间设置在报名开始时间之后");
            }
            // 如果不需要审核 需要缴费, 缴费的结束时间应该在报名时间之后
            if (BmProjectNeedPayEnum.PAY.getPayStatus().equals(project.getIsPay()) && null != project.getPayEndTime() && project.getPayEndTime().isBefore(project.getEndTime())) {
                InvalidRequestException.throwException(31051002, "请将缴费结束时间设置在报名结束时间之后");
            }
        }

        Project updateProject = new Project();
        updateProject.setId(projectId)
                .setUpdateDate(LocalDateTime.now())
                .setUpdateBy(iBaseLoginService.getUserId())
                .setDelFlag(Boolean.FALSE);
        // 编辑报名考试地址
        if (StrUtil.isEmpty(project.getAddress())) {
            updateProject.setAddress(configManager.getAddress() + "?projectId=" + project.getId() + "&officeId=" + project.getOfficeId());
        }
        // 编辑小程序报名地址
        if (StrUtil.isEmpty(project.getQrCodeUrl())) {
            String qrCodeUr = createBmQrCode(project.getOfficeId());
            Optional.ofNullable(qrCodeUr)
                    .ifPresent(updateProject::setQrCodeUrl);
        }
        if (null == project.getPayBeginTime()) {
            updateProject.setPayBeginTime(project.getBeginTime());
        }
        if (null == project.getPayEndTime()) {
            updateProject.setPayEndTime(project.getEndTime());
        }
        iProjectService.updateById(updateProject);
        return projectId;
    }

    private String createBmQrCode(String officeId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            String scene = "offId=";
            if (officeId.length() > 24) {
                scene = scene + officeId.substring(0, 24);
            } else {
                scene = scene + officeId;
            }
            map = (Map<String, Object>) tpsClient.getBmQRCodeHwCloud(officeId, scene, "pages/home/index", 260);
            log.info("getBmQRCodeHwCloud result :{}", JSON.toJSON(map));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return MapUtil.get(map, "obj", String.class);
    }

    /**
     * 装配报名基础信息
     *
     * @param param
     * @return
     */
    private Project assembleProjectBaseInfo(ProjectNodeParam param) {
        Project project = new Project();
        project.setId(param.getProjectId())
                .setUpdateDate(LocalDateTime.now())
                .setUpdateBy(iBaseLoginService.getUserId());
        param.getNodeList().stream()
                .forEach(data -> {
                    switch (NodeTypeEnum.getByCode(data.getNodeType())) {
                        case NOTICE:
                            ProjectNodeNoticeVo noticeVo = BeanUtil.toBean(data.getParam(), ProjectNodeNoticeVo.class);
                            BeanUtil.copyProperties(noticeVo, project);
                            break;
                        case VERIFY:
                            ProjectNodeVerifyVo verifyVo = BeanUtil.toBean(data.getParam(), ProjectNodeVerifyVo.class);
                            BeanUtil.copyProperties(verifyVo, project);
                            break;
                        case PAY:
                            ProjectNodePayVo payVo = BeanUtil.toBean(data.getParam(), ProjectNodePayVo.class);
                            BeanUtil.copyProperties(payVo, project);
                            break;
                        case ADMISSION:
                            ProjectNodeAdmissionVo admissionVo = BeanUtil.toBean(data.getParam(), ProjectNodeAdmissionVo.class);
                            BeanUtil.copyProperties(admissionVo, project);
                            break;
                        default:
                            break;
                    }
                });
        return project;
    }

    /**
     * 检查报名节点数据
     *
     * @param nodeList
     */
    private void checkProjectNodeData(String projectId, List<ProjectNodeVo> nodeList) {
        nodeList.stream()
                .forEach(data -> {
                    switch (NodeTypeEnum.getByCode(data.getNodeType())) {
                        case NOTICE:
                            ProjectNodeNoticeVo noticeVo = BeanUtil.toBean(data.getParam(), ProjectNodeNoticeVo.class);
                            if (ObjectUtil.isEmpty(noticeVo)) {
                                InvalidRequestException.throwException(31242312, "缺少报名须 知节点数据");
                            }
                            CheckUtil.check(noticeVo.getIsNotice(), IntRuler.notNull(31051112, "启用的报名须知内容不能为空"));
                            break;
                        case BASEINFO:
                            break;
                        case SUBJECT:
                            break;
                        case VERIFY:
                            ProjectNodeVerifyVo verifyVo = BeanUtil.toBean(data.getParam(), ProjectNodeVerifyVo.class);
                            if (ObjectUtil.isEmpty(verifyVo)) {
                                InvalidRequestException.throwException(31242313, "缺少资格审核节点数据");
                            }
                            CheckUtil.check(verifyVo.getIsVerify(), IntRuler.notNull(31242303, "是否审核状态不能为空"));
                            if (NumberUtil.equals(verifyVo.getIsVerify(), BmProjectVerifyEnum.UNVERIFY.getVerifyStatus())) {
                                break;
                            }
                            CheckUtil.check(verifyVo.getAuditEndTime(), ObjRuler.notNull(31242317, "审核结束时间不能为空"));
                            break;
                        case PAY:
                            ProjectNodePayVo payVo = BeanUtil.toBean(data.getParam(), ProjectNodePayVo.class);
                            if (ObjectUtil.isEmpty(payVo)) {
                                InvalidRequestException.throwException(31242314, "缺少缴费节点数据");
                            }
                            if (NumberUtil.equals(payVo.getIsPay(), BmProjectNeedPayEnum.UNPAY.getPayStatus())) {
                                break;
                            }

                            CheckUtil.check(payVo.getIsRefund(), IntRuler.notNull(31242304, "是否允许退款不能为空"))
                                    .check(payVo.getIsPay(), IntRuler.notNull(31242305, "是否需要缴费不能为空"))
                                    .check(payVo.getPayBeginTime(), ObjRuler.notNull(31242306, "缴费开始时间不能为空"))
                                    .check(payVo.getPayEndTime(), ObjRuler.notNull(31242307, "缴费结束时间不能为空"));
                            if (NumberUtil.equals(payVo.getIsRefund(), IsRefundEnum.YES.getCode())) {
                                CheckUtil.check(payVo.getRefuseTime(), ObjRuler.notNull(31242308, "退费截止时间不能为空"));
                            }
                            if (NumberUtil.equals(payVo.getIsRefund(), IsRefundEnum.YES.getCode())) {
                                if (payVo.getPayEndTime().isAfter(payVo.getRefuseTime())) {
                                    throw new InvalidRequestException(31242318, "退费截止时间不能早于缴费截止时间，请重新设置！");
                                }
                            }
                            break;
                        case ADMISSION:
                            ProjectNodeAdmissionVo admissionVo = BeanUtil.toBean(data.getParam(), ProjectNodeAdmissionVo.class);
                            if (ObjectUtil.isEmpty(admissionVo)) {
                                InvalidRequestException.throwException(31242315, "缺少准考证数据");
                            }
                            if (NumberUtil.equals(admissionVo.getIsNeedAdmission(), IsNeedAdmissionEnum.NO.getCode())) {
                                break;
                            }
                            CheckUtil.check(admissionVo.getIsNeedAdmission(), IntRuler.notNull(31242309, "是否需要打印准考证不能为空"))
                                    .check(admissionVo.getAdmissionBeginTime(), ObjRuler.notNull(31242310, "打印准考证开始时间不能为空"))
                                    .check(admissionVo.getAdmissionEndTime(), ObjRuler.notNull(31242311, "打印准考证结束时间不能为空"));
                            break;
                        default:
                            break;
                    }
                });
    }

    /**
     * 校验报名项目基础数据有效性
     *
     * @param param
     */
    private void verifyProjectBaseData(ProjectNodeBaseProjectParam param) {
        //校验项目报名时间
        if (null == param.getBeginTime() || null == param.getEndTime()
                || param.getBeginTime().isAfter(param.getEndTime())) {
            InvalidRequestException.throwException(31010107, "开始时间必须小于结束时间");
        }

        //校验同机构下面项目名称是否重复
        QueryWrapper<Project> tempwrapper = new QueryWrapper<Project>();
        tempwrapper.lambda()
                .eq(Project::getOfficeId, param.getOfficeId())
                .eq(Project::getProjectName, param.getProjectName())
                .eq(Project::getDelFlag, Boolean.FALSE)
                .ne(StringUtils.isNotEmpty(param.getId()), Project::getId, param.getId());
        List<Project> projectList = this.list(tempwrapper);
        if (CollectionUtils.isNotEmpty(projectList)) {
            InvalidRequestException.throwException(31010106, "项目名称已存在");
        }
    }
}
